package com.cygsunri.report.service.mediator;

import com.cygsunri.income.entity.IncomePlan;
import com.cygsunri.income.entity.IncomeTime;
import com.cygsunri.income.service.IncomePlanService;
import com.cygsunri.income.service.IncomeTimeService;
import com.cygsunri.report.entity.GeneralReport;
import com.cygsunri.report.entity.ReportElement;
import com.cygsunri.report.entity.ReportTime;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * 时间日期中介器
 */
@Component
public class DateTimeMediator extends AbstractReportMediator {

    @Autowired
    private IncomePlanService incomePlanService;

    @Autowired
    private IncomeTimeService incomeTimeService;

    @Override
    protected int mediateInner(GeneralReport report, Workbook workbook) {
        boolean found;
        do {
            // 每次填充完一行或者一列后,要重新开始迭代。因为纵向填充列时,会使得迭代器失效
            found = scanDateTime(report, workbook);
        } while (found);

        return 0;
    }

    private boolean scanDateTime(GeneralReport report, Workbook workbook) {
        boolean found = false;
        for (Sheet sheet : workbook) {
            for (Row row : sheet) {
                for (Cell cell : row) {
                    logger.info("单元格类型: {}", cell.getCellType());

                    if (cell.getCellType() == HSSFCell.CELL_TYPE_STRING) {
                        String context = cell.getStringCellValue();
                        logger.info("单元格内容: {}", context);

                        ReportElement element = makeElement(context);

                        if (element == null) {
                            continue;
                        }

                        //非时间序列时,直接填充GeneralReport中的日期
                        if (element.isTimeSequence()) {//时间序列型的,要额外填充表格
                            fillDateTime(report, sheet, element, cell);

                            found = true;
                        } else if (!element.isSequenceFilled()) {
                            if (element.isEnd()) {
                                element.setDate(report.getEndDate());
                            } else {
                                element.setDate(report.getDate());
                            }
                            //如果单元格中限定了日期类型,则以单元格中的为准
                            if (element.getDateType() == null) {
                                element.setDateType(report.getTimeType());
                            }

                            cell.setCellValue(makeString(element));
                        }
                    }
                }

                //由于存在跨row的填充,只能多次迭代
                if (found) {
                    break;
                }
            }
        }

        return found;
    }

    private void fillDateTime(GeneralReport report, Sheet sheet, ReportElement element, Cell cell) {
        int row = cell.getRowIndex();
        int col = cell.getColumnIndex();

        switch (report.getTimeType()) {
            case DAY: {
                //收益缓存填充日期
                if (element.getElementType() == 1) {
                    IncomePlan incomePlan = incomePlanService.getIncomePlan(element.getPlanName());
                    List<IncomeTime> incomeTimes = incomeTimeService.getIncomeTimeListByIncomePlanId(incomePlan.getId());
                    for (IncomeTime incomeTime : incomeTimes) {
                        element.setDate(report.getDate());
                        element.setTime(incomeTime.getEndTime());
                        element.setDateType(ReportTime.DAY);
                        element.setTimeSequence(false);
                        element.setSequenceFilled(true);
                        setCell(sheet, row, col, makeString(element));

                        if (element.isPortrait()) {
                            col++;
                        } else {
                            row++;
                        }
                    }
                } else {
                    for (int i = 1; i <= 24; i++) {
                        element.setDate(report.getDate());
                        element.setTime((i < 10 ? "0" + i : i) + ":00");
                        element.setDateType(ReportTime.DAY);
                        element.setTimeSequence(false);
                        element.setSequenceFilled(true);
                        setCell(sheet, row, col, makeString(element));

                        if (element.isPortrait()) {
                            col++;
                        } else {
                            row++;
                        }
                    }
                }
            }
            break;
            case WEEK: {
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                Calendar monday = Calendar.getInstance();
                Date date;
                try {
                    date = sdf.parse(report.getDate());
                } catch (ParseException e) {
                    cell.setCellValue("日期错误!");
                    logger.warn("周报表{}日期{}错误", report.getName(), report.getDate());
                    return;
                }

                monday.setTime(date);

                //获取周一
                int dayOfWeek = monday.get(Calendar.DAY_OF_WEEK) - 1;
                if (dayOfWeek == 0) {
                    dayOfWeek = 7;
                }

                monday.add(Calendar.DATE, -dayOfWeek + 1);

                for (int i = 0; i < 7; i++) {
                    element.setDate(sdf.format(monday.getTime()));
                    element.setDateType(ReportTime.WEEK);
                    element.setTimeSequence(false);
                    element.setSequenceFilled(true);
                    setCell(sheet, row, col, makeString(element));

                    if (element.isPortrait()) {
                        col++;
                    } else {
                        row++;
                    }

                    monday.add(Calendar.DAY_OF_WEEK, 1);
                }
            }
            break;
            case MONTH: {
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
                SimpleDateFormat targetSdf = new SimpleDateFormat("yyyy-MM-dd");
                Calendar month = Calendar.getInstance();
                Date date;
                try {
                    date = sdf.parse(report.getDate());
                } catch (ParseException e) {
                    cell.setCellValue("日期错误!");
                    logger.warn("月报表{}日期{}错误", report.getName(), report.getDate());
                    return;
                }

                month.setTime(date);
                for (int i = 0, max = month.getActualMaximum(Calendar.DAY_OF_MONTH); i < max; i++) {
                    element.setDate(targetSdf.format(month.getTime()));
                    element.setDateType(ReportTime.MONTH);
                    element.setTimeSequence(false);
                    element.setSequenceFilled(true);
                    setCell(sheet, row, col, makeString(element));

                    if (element.isPortrait()) {
                        col++;
                    } else {
                        row++;
                    }

                    month.add(Calendar.DAY_OF_MONTH, 1);
                }
            }
            break;
            case YEAR: {
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy");
                SimpleDateFormat targetSdf = new SimpleDateFormat("yyyy-MM");
                Calendar year = Calendar.getInstance();
                Date date;
                try {
                    date = sdf.parse(report.getDate());
                } catch (ParseException e) {
                    cell.setCellValue("日期错误!");
                    logger.warn("年报表{}日期{}错误", report.getName(), report.getDate());
                    return;
                }

                year.setTime(date);
                for (int i = 0, max = year.getActualMaximum(Calendar.MONTH); i <= max; i++) {
                    element.setDate(targetSdf.format(year.getTime()));
                    element.setDateType(ReportTime.YEAR);
                    element.setTimeSequence(false);
                    element.setSequenceFilled(true);
                    setCell(sheet, row, col, makeString(element));

                    if (element.isPortrait()) {
                        col++;
                    } else {
                        row++;
                    }

                    year.add(Calendar.MONTH, 1);
                }
            }
            break;
            default:
                break;
        }
    }
}
